/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */

package cgl.narada.service.storage.file;


import java.io.File;
import java.util.Properties;

import cgl.narada.util.logging.Logger;
import cgl.narada.util.logging.LoggerFactory;

import com.coyotegulch.jisp.BTreeIndex;
import com.coyotegulch.jisp.IndexedObjectDatabase;

/**
 * This class allocate and create database data and index files.
 * 
 */
public class BuildDB {

    final static Logger log =
        LoggerFactory.getLogger(BuildDB.class.getName());   

    public static final String sep = System.getProperty("file.separator");
    //public static String dir       = System.getProperty("NARADA_HOME");

    /**
     * Directory in which all the database data and index files are contained.
     */
    public static String dir       = null;

    public static final String DB_SUFFIX              = ".data";
    public static final String INDEX_SUFFIX           = ".index";

    public static final String ENTITY                 = "entity";
    public static final String PROFILE                = "profile";
    public static final String TEMPLATE               = "template";
    public static final String INVENTORY              = "inventory";
    public static String ENTITY_DB, PROFILE_DB, TEMPLATE_DB, INVENTORY_DB;
    public static String ENTITY_INVENTORY_DB, ENTITY_TEMPLATE_DB;
    public static String ENTITY_INDEX, PROFILE_INDEX, TEMPLATE_INDEX;
    public static String INVENTORY_INDEX, INVENTORY2_INDEX, ENTITY_TEMPLATE_INDEX;
    public static String ENTITY_INVENTORY_INDEX; 
    public static IndexedObjectDatabase 
	invDB,entDB,profDB,tempDB,entTempDB,entInvDB;
    public static BTreeIndex 
	invIndex,invIndex2,entIndex,profIndex,tempIndex,entTempIndex,entInvIndex;

    private static boolean db = false;

    public BuildDB() {}

    private boolean init() {
	if (dir == null) {
	    log.warn("base dir is null");
	    return false;
	}
	try {
	    File dirs = new File(dir);
	    if (!dirs.exists()) {
		dirs.mkdirs();
	    } 
	    if (!dirs.canRead() || !dirs.canWrite()) {
		log.error("access permission with " + dir + " needed");
	    }
	} catch (SecurityException se) {
	    se.printStackTrace();
	    log.error("couldn't allocate directory for database");
	}
	/*
	 * build databases and their indices tables. supposedly 
	 * large number of rows are assigned large Btree branching orders, 
	 * while small number of rows tables use smaller orders
	 */
	log.debug("start to build database");

	ENTITY_DB              = dir+sep+ENTITY+DB_SUFFIX;
	PROFILE_DB             = dir+sep+PROFILE+DB_SUFFIX;
	TEMPLATE_DB            = dir+sep+TEMPLATE+DB_SUFFIX;
	INVENTORY_DB           = dir+sep+INVENTORY+DB_SUFFIX;
	ENTITY_TEMPLATE_DB     = dir+sep+ENTITY+TEMPLATE+DB_SUFFIX;
	ENTITY_INVENTORY_DB    = dir+sep+ENTITY+INVENTORY+DB_SUFFIX;
	
	ENTITY_INDEX           = dir+sep+ENTITY+INDEX_SUFFIX;
	PROFILE_INDEX          = dir+sep+PROFILE+INDEX_SUFFIX;
	TEMPLATE_INDEX         = dir+sep+TEMPLATE+INDEX_SUFFIX;
	INVENTORY_INDEX        = dir+sep+INVENTORY+INDEX_SUFFIX;
	INVENTORY2_INDEX       = dir+sep+INVENTORY+"2"+INDEX_SUFFIX;
	ENTITY_TEMPLATE_INDEX  = dir+sep+ENTITY+TEMPLATE+INDEX_SUFFIX;
	ENTITY_INVENTORY_INDEX = dir+sep+ENTITY+INVENTORY+INDEX_SUFFIX;

	try { 
	    invDB=new IndexedObjectDatabase(INVENTORY_DB, true);
	    invIndex=new BTreeIndex(INVENTORY_INDEX, 47, 
				    new InventoryKey(), false);
	    invIndex2=new BTreeIndex(INVENTORY2_INDEX, 47, 
				     new InventoryKey2(), false);
	    
	    entDB=new IndexedObjectDatabase(ENTITY_DB, true);
	    entIndex=new BTreeIndex(ENTITY_INDEX, 47, 
				    new EntityKey(), false);
	    
	    profDB=new IndexedObjectDatabase(PROFILE_DB, true);
	    profIndex=new BTreeIndex(PROFILE_INDEX, 47, 
				     new ProfileKey(), false);

	    tempDB=new IndexedObjectDatabase(TEMPLATE_DB, true);
	    tempIndex=new BTreeIndex(TEMPLATE_INDEX, 47, 
				     new TemplateKey(), false);

	    entTempDB=new IndexedObjectDatabase(ENTITY_TEMPLATE_DB, true);
	    entTempIndex=new BTreeIndex(ENTITY_TEMPLATE_INDEX, 47, 
					new EntityTemplateKey(), false);

	    entInvDB=new IndexedObjectDatabase(ENTITY_INVENTORY_DB, true);
	    entInvIndex=new BTreeIndex(ENTITY_INVENTORY_INDEX, 47, 
				       new EntityInventoryKey(), false);
	} catch (Exception t) { t.printStackTrace();}
	log.debug("finish building database");
	return true;
    }
    
    //not good since we know dir is null and db is false initially but
    //we seem to say db can be true ...
    public boolean build() { if (!db) db=init(); return db; }

    //can set other properties than base dir here
    public void setProperties(Properties props) {
	dir = props.getProperty("FileStorageBaseDir");
	if (dir != null) {
	    String osName = System.getProperty("os.name");
	    if (osName.toLowerCase().indexOf("windows") == -1) {
		if (!dir.startsWith("/")) {
		    log.warn("file storage base dir should begin with /");
		}
	    } else { 
		if (dir.toLowerCase().indexOf(":\\") == -1) {
		    log.warn("file storage base dir should include :\\");
		}
	    }
	    if (dir.endsWith(sep)) dir = dir.substring(0, dir.length()-1); 
	}
	log.debug("file storage dir: "+dir);
    }

}

